package org.jtools.logwrapper.proxy.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.jtools.logwrapper.proxy.LoggerProxy;
import org.jtools.sanitizer.Sanitizer;

public class Log4JLoggerProxy extends Logger implements LoggerProxy<Logger> {

    private static final List<Sanitizer> sanitizerList = new ArrayList<Sanitizer>();

    private final Logger logger;

    public Log4JLoggerProxy(String clazz, List<Sanitizer> sanitizers) {
        super(clazz);
        sanitizerList.addAll(sanitizers);
        this.logger = Logger.getLogger(clazz);
    }

    public Log4JLoggerProxy(String className, Sanitizer... sanitizerslist) {
        this(className, Arrays.asList(sanitizerslist));
    }

    @Override
    public void debug(Object... messages) {
        this.debug(getMessage(messages));
    }

    @Override
    public void debug(Object message) {
        logger.debug(runSanitizers(message));
    }

    @Override
    public void debug(Object message, Throwable t) {
        logger.debug(runSanitizers(message), (Throwable) runSanitizers(t));
    }

    @Override
    public void error(Object... messages) {
        this.error(getMessage(messages));
    }

    @Override
    public void error(Object message) {
        logger.error(runSanitizers(message));
    }

    @Override
    public void error(Object message, Throwable t) {
        logger.error(runSanitizers(message), (Throwable) runSanitizers(t));
    }

    @Override
    public void info(Object... messages) {
        final Throwable t = getThrowable(messages);

        if (t != null)
            this.info(getMessage(messages), t);
        else
            this.info(getMessage(messages));
    }

    @Override
    public void info(Object message) {
        logger.info(runSanitizers(message));
    }

    @Override
    public void info(Object message, Throwable t) {
        logger.info(runSanitizers(message), (Throwable) runSanitizers(t));
    }

    @Override
    public synchronized void setLevel(Level level) {
        this.logger.setLevel(level);
    }

    public void trace(Object... messages) {
        this.trace(getMessage(messages));
    }

    @Override
    public void trace(Object message) {
        logger.trace(runSanitizers(message));
    }

    @Override
    public void trace(Object message, Throwable t) {
        logger.trace(runSanitizers(message), (Throwable) runSanitizers(t));
    }

    public void warn(Object... messages) {
        this.warn(getMessage(messages));
    }

    @Override
    public void warn(Object message) {
        logger.warn(runSanitizers(message));
    }

    @Override
    public void warn(Object message, Throwable t) {
        logger.warn(runSanitizers(message), (Throwable) runSanitizers(t));
    }

    private String getMessage(Object[] messages) {
        if (messages == null)
            return null;

        final StringBuilder sb = new StringBuilder();

        for (int i = 0; i < messages.length; i++) {
            if (messages[i] instanceof Throwable)
                sb.append(((Throwable) messages[i]).getMessage()).append(' ');
            else
                sb.append(messages[i]).append(' ');
        }

        return sb.toString().trim();
    }

    private Throwable getThrowable(Object[] messages) {
        for (int i = 0; i < messages.length; i++)
            if (messages[i] instanceof Throwable)
                return (Throwable) messages[i];

        return null;
    }

    private Object runSanitizers(Object obj) {
        for (Sanitizer sanitizer : sanitizerList)
            obj = sanitizer.sanitize(obj);

        return obj;
    }
}